﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 2019/9/7
 * Time: 10:49
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Drawing;
using System.Windows.Forms;

using System.Collections.Generic;

using IWshRuntimeLibrary;
using MiniJSON;

namespace QStarter
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : BaseForm
	{
//		配置文件
		string ConfigFile = Environment.CurrentDirectory + "\\QStarter.cfg";
//		配置信息
		public Dictionary<string, object> Configs = new Dictionary<string, object>();
		
//		App信息
		Dictionary<string, string> Apps = new Dictionary<string, string>();

//		配置窗体
		ConfigForm CF = null;
		public bool CFClosed = true;
		
//		配置是否有变化
		public bool IsConfigChange;
		
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//
			// TODO: Add constructor code after the InitializeComponent() call.
			//
			
			this.Text = "QStarter".GetHashCode().ToString();
			
//			初始化配置
			this.Init();
			
//			初始化配置窗体
			this.CF = new ConfigForm(this);

			this.IsConfigChange = false;
			
			NativeMethods.SetForegroundWindow(this.Handle);
		}
		
//		初始化
		void Init()
		{
//			获取配置
			if (System.IO.File.Exists(this.ConfigFile))
			{
				try {
					this.Configs = Json.Deserialize(System.IO.File.ReadAllText(this.ConfigFile)) as Dictionary<string, object>;
				} catch (Exception) {
					MessageBox.Show("打开配置文件失败");
					System.Environment.Exit(0);
				}
			} else {
				try {
					System.IO.File.WriteAllText(this.ConfigFile, res.configs);
					this.Configs = Json.Deserialize(res.configs) as Dictionary<string, object>;
				} catch (Exception) {
					MessageBox.Show("创建默认配置文件失败");
					System.Environment.Exit(0);
				}
			}
			
//			初始化配置
			this.Opacity = (Double)this.ConfigToInt("Opacity") / 100;
			this.Location = new Point(this.ConfigToInt("LocationX"), this.ConfigToInt("LocationY"));
			this.isLocation = this.ConfigToInt("isLocation");
			this.Size = new Size(this.ConfigToInt("Width"), this.ConfigToInt("Height"));
			this.isResize = this.ConfigToInt("isResize");
			this.BackColor = Color.FromArgb(this.ConfigToInt("ColorR"), this.ConfigToInt("ColorG"), this.ConfigToInt("ColorB"));
			
//			注册热键
			if (this.Configs["HotKey"].ToString().Length > 1)
			{
				string error = HotKey.RegKeyFromString(this.Handle, 0, this.Configs["HotKey"].ToString());
				if (error.Length > 0)
				{
					MessageBox.Show(error);
					this.Configs["HotKey"] = "无";
				}
			}
			
//			获取Apps并生成
			List<object> apps = (List<object>)this.Configs["Apps"];
			if (apps.Count > 0)
			{
				List<string> files = new List<string>();
				foreach (object app in apps) { files.Add(app.ToString()); }
				this.CreateApp(files.ToArray());
			}
			
//			更新控件
			this.UpdateControls();
		}
		
//		新建App（.exe、.lnk）
		void CreateApp(string[] files)
		{
			string extension = string.Empty;
			string fullname = string.Empty;
			foreach (string f in files)
			{
				extension = System.IO.Path.GetExtension(f);
				if (extension == ".exe" ||  extension == ".lnk")
				{
					if (extension == ".lnk")
					{
						WshShell shell = new WshShellClass();
						IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(f);
						fullname = shortcut.TargetPath;
					} 
					else
					{
						fullname = f;
					}
					
					this.CreateButton(fullname);
				}
			}
		}
		
//		生成App按钮
		void CreateButton(string fullname)
		{
			string name = "btn" + fullname.GetHashCode().ToString();
			
			if (!this.Apps.ContainsKey(name)) {
				this.Apps.Add(name, fullname);
				
				Button btn = new Button();
				btn.Name = name;
				btn.BackColor = Color.Transparent;
				btn.FlatStyle = FlatStyle.Flat;
				btn.FlatAppearance.BorderSize = 0;
				
				btn.BackgroundImageLayout = ImageLayout.Center;
				btn.Margin = new Padding(0);
				btn.Padding = new Padding(0);
				btn.UseVisualStyleBackColor = false;
				btn.Text = string.Empty;
				btn.ContextMenuStrip = this.CMS;
				btn.Enter += new System.EventHandler(this.BanFocus);
				btn.Click += new EventHandler(this.AppClick);
				btn.MouseEnter += new System.EventHandler(this.ShowAppName);
				btn.MouseLeave += new System.EventHandler(this.HideAppName);
				btn.MouseMove += new MouseEventHandler(this.AppMouseMove);
				btn.GiveFeedback += new GiveFeedbackEventHandler(this.AppGiveFeedback);
				
				this.FLP.Controls.Add(btn);
			}
		}
		
//		更新控件信息（大小、颜色）
		public void UpdateControls()
		{
			int colorR = this.ConfigToInt("ColorR") - 15 > 0 ? this.ConfigToInt("ColorR") - 15 : 0;
			int colorG = this.ConfigToInt("ColorG") - 15 > 0 ? this.ConfigToInt("ColorG") - 15 : 0;
			int colorB = this.ConfigToInt("ColorB") - 15 > 0 ? this.ConfigToInt("ColorB") - 15 : 0;
			
//			隐藏、设置、关闭按钮的颜色
			this.btnClose.FlatAppearance.MouseDownBackColor = Color.FromArgb(colorR, colorG, colorB);
			this.btnClose.FlatAppearance.MouseOverBackColor = Color.FromArgb(colorR, colorG, colorB);
			this.btnMenu.FlatAppearance.MouseDownBackColor = Color.FromArgb(colorR, colorG, colorB);
			this.btnMenu.FlatAppearance.MouseOverBackColor = Color.FromArgb(colorR, colorG, colorB);
			this.btnHide.FlatAppearance.MouseDownBackColor = Color.FromArgb(colorR, colorG, colorB);
			this.btnHide.FlatAppearance.MouseOverBackColor = Color.FromArgb(colorR, colorG, colorB);
			
//			遍历App，设置大小和颜色
			foreach (Control control in this.FLP.Controls)
			{
				Button btn = (Button)control;
				btn.FlatAppearance.MouseDownBackColor = Color.FromArgb(colorR, colorG, colorB);
				btn.FlatAppearance.MouseOverBackColor = Color.FromArgb(colorR, colorG, colorB);
				btn.Size = new Size(this.ConfigToInt("IconSize") + 20, this.ConfigToInt("IconSize") + 20);
				btn.BackgroundImage = IconTools.GetIcon(this.Apps[btn.Name], this.ConfigToInt("IconSize"));
			}
		}
		
//		配置参数转int
		public int ConfigToInt(string key)
		{
			int number = 0;
			bool error = false;
			
			if (this.Configs.ContainsKey(key)) { error = !int.TryParse(this.Configs[key].ToString(), out number); }
			else { error = true; }
	
			if (error)
			{
				MessageBox.Show("配置文件错误");
				System.Environment.Exit(0);
			}
			
			return number;
		}
		
//		保存当前配置
		void WriteConfigs()
		{
//			窗口位置大小
			this.Configs["LocationX"] = this.Location.X;
			this.Configs["LocationY"] = this.Location.Y;
			this.Configs["Width"] = this.Size.Width;
			this.Configs["Height"] = this.Size.Height;
			
//			写入Apps
			List<string> apps = new List<string>();
			foreach (string app in this.Apps.Values) { apps.Add(app); }
			this.Configs["Apps"] = apps;
			
			try {
				System.IO.File.WriteAllText(this.ConfigFile, Json.Serialize(this.Configs));
			} catch (Exception) {
				MessageBox.Show("写入配置文件失败");
			}
			
			this.IsConfigChange = false;
		}
		
//		拖拽排序及新建App
		void FLPDragEnter(object sender, DragEventArgs e) { e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Link : DragDropEffects.Move; }
		
		void FLPDragDrop(object sender, DragEventArgs e)
		{
			if (e.Effect == DragDropEffects.Move) // App排序
			{
				Button button = (Button)e.Data.GetData(typeof(Button));
				Point point = this.FLP.PointToClient(new Point(e.X, e.Y));
				Control control = this.FLP.GetChildAtPoint(point);
				if (control != null && control != button)
				{
					int sourceIndex = this.FLP.Controls.GetChildIndex(button);
					int targerIndex = this.FLP.Controls.GetChildIndex(control);
					
//					生成App的FullName数组
					string[] appName = new string[this.Apps.Count]; // 排序后
					this.Apps.Values.CopyTo(appName, 0);
					string[] appNameClone = appName.Clone() as string[]; // 排序前
					
//					FullName数组开始排序
					for (int i = 0; i < appName.Length; i++)
					{
						if (targerIndex < sourceIndex && targerIndex <= i && i < sourceIndex) // 往前拖
						{
							appName[i+1] = appNameClone[i];
						}
						
						if (sourceIndex < targerIndex && sourceIndex <= i && i < targerIndex) // 往前拖
						{
							appName[i] = appName[i+1];
						}
					}
//					将要拖动的app放入目标位置
					appName[targerIndex] = appNameClone[sourceIndex];
					
//					更新Apps及容器
					this.Apps.Clear();
					string name = string.Empty;
					for (int i = 0; i < appName.Length; i++) {
						name = "btn" + appName[i].GetHashCode().ToString();
						this.Apps.Add(name, appName[i]);
						this.FLP.Controls.SetChildIndex(this.FLP.Controls.Find(name, false)[0], i);
					}
					
					this.IsConfigChange = true;
				}
			}
			else if (e.Effect == DragDropEffects.Link) // 新建App
			{
				CreateApp((string[])e.Data.GetData(DataFormats.FileDrop));
				this.UpdateControls();
				
				this.IsConfigChange = true;
			}
		}

//		拖拽排序
		void AppMouseMove(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				Button button = sender as Button;
				button.DoDragDrop(button, DragDropEffects.Move);
			}
		}
		
//		更改拖拽排序时的图标
		void AppGiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
			e.UseDefaultCursors = false;
			Cursor.Current = Cursors.SizeAll;
		}
		
//		app点击事件
		void AppClick(object sender, EventArgs e)
		{
			Button btn = sender as Button;
			NativeMethods.ShellExecute(IntPtr.Zero, "open", this.Apps[btn.Name], null, null, 1);
			
			if (this.ConfigToInt("FocusHide") > 0) { this.Hide(); }
		}
		
//		打开App目录
		void CMSOpenFClick(object sender, EventArgs e)
		{
			NativeMethods.ShellExecute(IntPtr.Zero, "open", System.IO.Path.GetDirectoryName(this.Apps[this.CMS.SourceControl.Name]), null, null, 1);
		}
		
//		按App名称排序
		void CMSSortClick(object sender, EventArgs e)
		{
//			新建App字典<name，fullname>
			Dictionary<string, string> dict = new Dictionary<string, string>();
			foreach (string app in this.Apps.Values) { dict.Add(System.IO.Path.GetFileNameWithoutExtension(app), app); }
			
//			生成App的Name数组并排序
			string[] appName = new string[dict.Count];
			dict.Keys.CopyTo(appName, 0);
			Array.Sort(appName);
			
//			更新Apps及容器
			this.Apps.Clear();
			string name = string.Empty;
			for (int i = 0; i < appName.Length; i++) { 
				name = "btn" + dict[appName[i]].GetHashCode().ToString();
				this.Apps.Add(name, dict[appName[i]]);
				this.FLP.Controls.SetChildIndex(this.FLP.Controls.Find(name, false)[0], i);
			}
			
			this.IsConfigChange = true;
		}
		
//		删除App
		void CMSDelClick(object sender, EventArgs e)
		{
			this.Apps.Remove(this.CMS.SourceControl.Name);
			this.FLP.Controls.RemoveByKey(this.CMS.SourceControl.Name);
			
			this.IsConfigChange = true;
		}
		
//		阻止获取焦点
		void BanFocus(object sender, System.EventArgs e) { this.lbTitle.Focus(); }
		
//		标题栏显示隐藏app名称
		void ShowAppName(object sender, System.EventArgs e) 
		{
			string key = (sender as Button).Name;
			if (this.Apps.ContainsKey(key))
			{
				this.lbTitle.Text = System.IO.Path.GetFileNameWithoutExtension(this.Apps[key]); 
			}
			
		}
		void HideAppName(object sender, System.EventArgs e) { this.lbTitle.Text = "QStarter"; }

//		最小化/隐藏按钮
		void BtnHideClick(object sender, EventArgs e) { this.Hide(); }
		
//		设置
		void BtnMenuClick(object sender, EventArgs e) 
		{ 
			this.CFClosed = false;
			this.CF.ShowDialog(); 
		}
		
//		关闭按钮
		void BtnCloseClick(object sender, EventArgs e)
		{
			this.Close();
			System.Environment.Exit(0);
		}		
		
//		位置是否变化
		void MainFormLocationChanged(object sender, EventArgs e) { if (this.Visible) { this.IsConfigChange = true; } }
		
//		大小是否变化
		void MainFormSizeChanged(object sender, EventArgs e)
		{
			if (this.Visible)
			{
				if (this.ConfigToInt("Width") != this.Size.Width || this.ConfigToInt("Height") != this.Size.Height)
				{
					int xFill = (this.Size.Width - 10) / ((this.ConfigToInt("IconSize") + 20));
					int yFill = (this.Size.Height - 45) / ((this.ConfigToInt("IconSize") + 20));
					this.Configs["Width"] = (this.ConfigToInt("IconSize") + 20) * xFill + 10;
					this.Configs["Height"] = (this.ConfigToInt("IconSize") + 20) * yFill + 45 + 5;
					this.Size = new Size(this.ConfigToInt("Width"), this.ConfigToInt("Height"));
					
					this.IsConfigChange = true;
				}
			}
		}
		
//		主界面失去焦点事件
		void MainFormDeactivate(object sender, EventArgs e) { if (this.ConfigToInt("FocusHide") > 0 && this.CFClosed) { this.Hide(); } }
		
//		程序退出事件
		void MainFormFormClosed(object sender, FormClosedEventArgs e)
		{
			if (this.Configs["HotKey"].ToString().Length > 1) { HotKey.UnRegKey(this.Handle, 0); }
			if (this.IsConfigChange) { this.WriteConfigs(); }
		}
		
//		隐藏时执行垃圾回收及保存配置
		void MainFormVisibleChanged(object sender, EventArgs e)
		{
			if (!this.Visible)
			{
				if (this.IsConfigChange) { this.WriteConfigs(); }
				NativeMethods.ClearMemory();
			}
		}
	}
}
